﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Silverlight.ControlToolkit.Windows
{

    // Summary:
    //     Specifies constants defining which buttons to display on a System.Windows.Forms.MessageWindow.
    public enum MessageWindowButtons
    {
        // Summary:
        //     The message box contains an OK button.
        OK = 0,
        //
        // Summary:
        //     The message box contains OK and Cancel buttons.
        OKCancel = 1,
        //
        // Summary:
        //     The message box contains Abort, Retry, and Ignore buttons.
        AbortRetryIgnore = 2,
        //
        // Summary:
        //     The message box contains Yes, No, and Cancel buttons.
        YesNoCancel = 3,
        //
        // Summary:
        //     The message box contains Yes and No buttons.
        YesNo = 4,
        //
        // Summary:
        //     The message box contains Retry and Cancel buttons.
        RetryCancel = 5,
    }

    // Summary:
    //     Specifies constants defining the default button on a System.Windows.Forms.MessageWindow.
    public enum MessageWindowDefaultButton
    {
        // Summary:
        //     The first button on the message box is the default button.
        Button1 = 0,
        //
        // Summary:
        //     The second button on the message box is the default button.
        Button2 = 1,
        //
        // Summary:
        //     The third button on the message box is the default button.
        Button3 = 3,
    }

    // Summary:
    //     Specifies constants defining which information to display.
    public enum MessageWindowIcon
    {
        // Summary:
        //     The message box contain no symbols.
        None = 0,
        //
        // Summary:
        //     The message box contains a symbol consisting of white X in a circle with
        //     a red background.
        Error = 16,
        //
        // Summary:
        //     The message box contains a symbol consisting of a question mark in a circle.
        Question = 32,
        //
        // Summary:
        //     The message box contains a symbol consisting of an exclamation point in a
        //     triangle with a yellow background.
        Warning = 48,
        //
        // Summary:
        //     The message box contains a symbol consisting of a lowercase letter i in a
        //     circle.
        Information = 64,
    }



    [TemplatePart(Name = "RootElement", Type = typeof(FrameworkElement))]
    [TemplatePart(Name = "MessageBorderElement", Type = typeof(FrameworkElement))]
    [TemplatePart(Name = "TitleBarElement", Type = typeof(FrameworkElement))]
    [TemplatePart(Name = "TitleTextElement", Type = typeof(TextBlock))]
    [TemplatePart(Name = "MessageTextElement", Type = typeof(TextBlock))]
    [TemplatePart(Name = "OkButtonElement", Type = typeof(Button))]
    [TemplatePart(Name = "CancelButtonElement", Type = typeof(Button))]
    [TemplatePart(Name = "YesButtonElement", Type = typeof(Button))]
    [TemplatePart(Name = "NoButtonElement", Type = typeof(Button))]
    [TemplatePart(Name = "AbortButtonElement", Type = typeof(Button))]
    [TemplatePart(Name = "RetryButtonElement", Type = typeof(Button))]
    [TemplatePart(Name = "IgnoreButtonElement", Type = typeof(Button))]
    [TemplatePart(Name = "ButtonHolderElement", Type = typeof(StackPanel))]
    [TemplatePart(Name = "MessageIconErrorElement", Type = typeof(Image))]
    [TemplatePart(Name = "MessageIconQuestionElement", Type = typeof(Image))]
    [TemplatePart(Name = "MessageIconWarnElement", Type = typeof(Image))]
    [TemplatePart(Name = "MessageIconInfoElement", Type = typeof(Image))]
    public partial class MessageWindow : Control
    {

        private Button OkButtonElement { get; set; }
        private Button CancelButtonElement { get; set; }
        private Button YesButtonElement { get; set; }
        private Button NoButtonElement { get; set; }
        private Button AbortButtonElement { get; set; }
        private Button RetryButtonElement { get; set; }
        private Button IgnoreButtonElement { get; set; }
        public FrameworkElement MessageBorderElement { get; set; }
        private FrameworkElement TitleBarElement { get; set; }
        private FrameworkElement RootElement { get; set; }
        private StackPanel ButtonHolderElement { get; set; }
        private Image MessageIconErrorElement { get; set; }
        private Image MessageIconQuestionElement { get; set; }
        private Image MessageIconWarnElement { get; set; }
        private Image MessageIconInfoElement { get; set; }

        //public static readonly DependencyProperty BackgroundProperty =
        //    DependencyProperty.Register("Background", typeof(Color), typeof(MessageWindow),
        //                        new PropertyMetadata(new PropertyChangedCallback(BackgroundChangedCallback)));

        private static void BackgroundChangedCallback(DependencyObject obj,
                                DependencyPropertyChangedEventArgs args)
        {
            if (obj != null)
                ((MessageWindow)obj).MessageBorderElement.SetValue(Border.BackgroundProperty, args.NewValue);
        }


        //public Brush Background
        //{
        //    get
        //    {
        //        return (Brush)GetValue(BackgroundProperty);
        //    }

        //    set
        //    {
        //        SetValue(BackgroundProperty, value);
        //    }
        //}

        public static readonly DependencyProperty ForegroundProperty =
            DependencyProperty.Register("Foreground", typeof(Color), typeof(MessageWindow),
                                new PropertyMetadata(new PropertyChangedCallback(ForegroundChangedCallback)));

        private static void ForegroundChangedCallback(DependencyObject obj,
                                DependencyPropertyChangedEventArgs args)
        {
            if (obj != null)
                ((MessageWindow)obj).MessageTextElement.SetValue(TextBlock.ForegroundProperty, args.NewValue);
        }

        public Brush Foreground
        {
            get
            {
                return (Brush)GetValue(ForegroundProperty);
            }

            set
            {
                SetValue(ForegroundProperty, value);
            }
        }


        public static readonly DependencyProperty BorderBrushProperty =
            DependencyProperty.Register("BorderBrush", typeof(Color), typeof(MessageWindow),
                                new PropertyMetadata(new PropertyChangedCallback(BorderBrushChangedCallback)));

        private static void BorderBrushChangedCallback(DependencyObject obj,
                                DependencyPropertyChangedEventArgs args)
        {
            if (obj != null)
                ((MessageWindow)obj).MessageBorderElement.SetValue(Border.BorderBrushProperty, args.NewValue);
        }

        public Brush BorderBrush
        {
            get
            {
                return (Brush)GetValue(BorderBrushProperty);
            }

            set
            {
                SetValue(BorderBrushProperty, value);
            }
        }

        public static readonly DependencyProperty FontSizeProperty =
            DependencyProperty.Register("FontSize", typeof(double), typeof(MessageWindow),
                                new PropertyMetadata(new PropertyChangedCallback(FontSizeChangedCallback)));

        private static void FontSizeChangedCallback(DependencyObject obj,
                                DependencyPropertyChangedEventArgs args)
        {
            if (obj != null)
                ((MessageWindow)obj).MessageTextElement.SetValue(TextBlock.FontSizeProperty, args.NewValue);
        }

        public double FontSize
        {
            get
            {
                return (double)GetValue(FontSizeProperty);
            }

            set
            {
                SetValue(FontSizeProperty, value);
            }
        }


        public static Style DefaultStyle { get; set; }

        public static string DefaultStyleXaml
        {
            set
            {
                DefaultStyle = System.Windows.Markup.XamlReader.Load(value) as Style;
            }

        }

        public static ControlTemplate DefaultTemplate { get; set; }

        public static string DefaultTemplateXaml
        {
            set
            {
                DefaultTemplate = System.Windows.Markup.XamlReader.Load(value) as ControlTemplate;
            }

        }

        private TextBlock messageTextElement;

        private TextBlock MessageTextElement
        {
            get { return messageTextElement; }

            set
            {
                messageTextElement = value;

                if (messageTextElement != null)
                {
                    messageTextElement.Text = value.Text;
                }
            }

        }

        private TextBlock titleTextElement;

        private TextBlock TitleTextElement
        {
            get { return titleTextElement; }

            set
            {
                titleTextElement = value;

                if (titleTextElement != null)
                {
                    titleTextElement.Text = value.Text;
                }
            }

        }


        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            RootElement = (FrameworkElement)GetTemplateChild("RootElement");
            MessageBorderElement = (FrameworkElement)GetTemplateChild("MessageBorderElement");
            TitleBarElement = (FrameworkElement)GetTemplateChild("TitleBarElement");
            TitleTextElement = (TextBlock)GetTemplateChild("TitleTextElement");
            MessageTextElement = (TextBlock)GetTemplateChild("MessageTextElement");
            OkButtonElement = (Button)GetTemplateChild("OkButtonElement");
            CancelButtonElement = (Button)GetTemplateChild("CancelButtonElement");
            YesButtonElement = (Button)GetTemplateChild("YesButtonElement");
            NoButtonElement = (Button)GetTemplateChild("NoButtonElement");
            AbortButtonElement = (Button)GetTemplateChild("AbortButtonElement");
            RetryButtonElement = (Button)GetTemplateChild("RetryButtonElement");
            IgnoreButtonElement = (Button)GetTemplateChild("IgnoreButtonElement");
            ButtonHolderElement = (StackPanel)GetTemplateChild("ButtonHolderElement");
            MessageIconErrorElement = (Image)GetTemplateChild("MessageIconErrorElement");
            MessageIconQuestionElement = (Image)GetTemplateChild("MessageIconQuestionElement");
            MessageIconWarnElement = (Image)GetTemplateChild("MessageIconWarnElement");
            MessageIconInfoElement = (Image)GetTemplateChild("MessageIconInfoElement");

        }


        public static ModalDialog Show(string messageText)
        {
            return Show(null, messageText, null, MessageWindowButtons.OK, MessageWindowDefaultButton.Button1, MessageWindowIcon.None);
        }

        public static ModalDialog Show(string messageText, string caption)
        {
            return Show(null, messageText, caption, MessageWindowButtons.OK, MessageWindowDefaultButton.Button1, MessageWindowIcon.None);
        }

        public static ModalDialog Show(FrameworkElement owner, string messageText)
        {
            return Show(owner, messageText, null, MessageWindowButtons.OK, MessageWindowDefaultButton.Button1, MessageWindowIcon.None);
        }

        public static ModalDialog Show(FrameworkElement owner, string messageText, string caption)
        {
            return Show(owner, messageText, caption, MessageWindowButtons.OK, MessageWindowDefaultButton.Button1, MessageWindowIcon.None);
        }

        public static ModalDialog Show(string messageText, MessageWindowButtons buttons)
        {
            return Show(null, messageText, null, buttons, MessageWindowDefaultButton.Button1, MessageWindowIcon.None);
        }

        public static ModalDialog Show(string messageText, string caption, MessageWindowButtons buttons)
        {
            return Show(null, messageText, caption, buttons, MessageWindowDefaultButton.Button1, MessageWindowIcon.None);
        }

        public static ModalDialog Show(string messageText, MessageWindowButtons buttons, MessageWindowDefaultButton defaultButton)
        {
            return Show(null, messageText, null, buttons, defaultButton, MessageWindowIcon.None);
        }

        public static ModalDialog Show(string messageText, string caption, MessageWindowButtons buttons, MessageWindowDefaultButton defaultButton)
        {
            return Show(null, messageText, caption, buttons, defaultButton, MessageWindowIcon.None);
        }

        public static ModalDialog Show(string messageText, MessageWindowButtons buttons, MessageWindowDefaultButton defaultButton, MessageWindowIcon icon)
        {
            return Show(null, messageText, null, buttons, defaultButton, icon);
        }

        public static ModalDialog Show(string messageText, string caption, MessageWindowButtons buttons, MessageWindowDefaultButton defaultButton, MessageWindowIcon icon)
        {
            return Show(null, messageText, caption, buttons, defaultButton, icon);
        }

        public static ModalDialog Show(FrameworkElement owner, string messageText, MessageWindowButtons buttons)
        {
            return Show(owner, messageText, null, buttons, MessageWindowDefaultButton.Button1, MessageWindowIcon.None);
        }

        public static ModalDialog Show(FrameworkElement owner, string messageText, string caption, MessageWindowButtons buttons)
        {
            return Show(owner, messageText, caption, buttons, MessageWindowDefaultButton.Button1, MessageWindowIcon.None);
        }

        public static ModalDialog Show(FrameworkElement owner, string messageText, MessageWindowButtons buttons, MessageWindowDefaultButton defaultButton)
        {
            return Show(owner, messageText, null, buttons, defaultButton, MessageWindowIcon.None);
        }

        public static ModalDialog Show(FrameworkElement owner, string messageText, string caption, MessageWindowButtons buttons, MessageWindowDefaultButton defaultButton)
        {
            return Show(owner, messageText, caption, buttons, defaultButton, MessageWindowIcon.None);
        }

        public static ModalDialog Show(FrameworkElement owner, string messageText, MessageWindowButtons buttons, MessageWindowDefaultButton defaultButton, MessageWindowIcon icon)
        {
            return Show(owner, messageText, null, buttons, defaultButton, icon);
        }

        public static ModalDialog Show(FrameworkElement owner, string messageText, string caption, MessageWindowButtons buttons, MessageWindowDefaultButton defaultButton, MessageWindowIcon icon)
        {
            return Show(owner, messageText, caption, buttons, defaultButton, icon, DefaultTemplate);
        }

        public static ModalDialog Show(FrameworkElement owner, string messageText, string caption, MessageWindowButtons buttons, MessageWindowDefaultButton defaultButton, MessageWindowIcon icon, string templateXaml)
        {
            ControlTemplate objTemplate = System.Windows.Markup.XamlReader.Load(templateXaml) as ControlTemplate;
            return Show(owner, messageText, caption, buttons, defaultButton, icon, objTemplate);
        }

        public static ModalDialog Show(FrameworkElement owner, string messageText, string caption, MessageWindowButtons buttons, MessageWindowDefaultButton defaultButton, MessageWindowIcon icon, ControlTemplate objTemplate)
        {

            MessageWindow objMessageWindowInstance = new MessageWindow();

            objMessageWindowInstance.ApplyDefaultStyleTemplate(DefaultStyle, objTemplate);

            //if (objTemplate == null)
            //{
            //    if (DefaultTemplate == null)
            //        DefaultTemplate = System.Windows.Markup.XamlReader.Load(Resource.MessageWindowTemplateXml) as ControlTemplate;

            //    objTemplate = DefaultTemplate;
            //}

            //objMessageWindowInstance.Template = objTemplate;
            //objMessageWindowInstance.ApplyTemplate();

            //Append a space at the end so that the complext text is visible
            //This issue got introduced in 2.0 release version. For some reasons it truncates the last word if it 
            //does not have any space next to it
            if (messageText != null)
                objMessageWindowInstance.MessageTextElement.Text = messageText + " ";
            else
                objMessageWindowInstance.MessageTextElement.Text = "";

            //if (caption != null)
            //    objMessageWindowInstance.TitleTextElement.Text = caption;
            //else
            //    objMessageWindowInstance.TitleTextElement.Text = "";

            if (objMessageWindowInstance.MessageBorderElement is WindowPanel)
            {
                if (caption != null)
                    ((WindowPanel)objMessageWindowInstance.MessageBorderElement).HeaderText = caption;
                else
                    ((WindowPanel)objMessageWindowInstance.MessageBorderElement).HeaderText = "My Test Header";
            }

            //Clear all buttons 
            objMessageWindowInstance.ButtonHolderElement.Children.Clear();

            switch (buttons)
            {
                case MessageWindowButtons.OK:
                    objMessageWindowInstance.ButtonHolderElement.Children.Add(objMessageWindowInstance.OkButtonElement);
                    objMessageWindowInstance.OkButtonElement.SetValue(ModalDialog.ActionResult, DialogResult.OK);
                    break;

                case MessageWindowButtons.OKCancel:
                    objMessageWindowInstance.ButtonHolderElement.Children.Add(objMessageWindowInstance.OkButtonElement);
                    objMessageWindowInstance.ButtonHolderElement.Children.Add(objMessageWindowInstance.CancelButtonElement);
                    objMessageWindowInstance.OkButtonElement.SetValue(ModalDialog.ActionResult, DialogResult.OK);
                    objMessageWindowInstance.CancelButtonElement.SetValue(ModalDialog.ActionResult, DialogResult.Cancel);
                    break;

                case MessageWindowButtons.YesNo:
                    objMessageWindowInstance.ButtonHolderElement.Children.Add(objMessageWindowInstance.YesButtonElement);
                    objMessageWindowInstance.ButtonHolderElement.Children.Add(objMessageWindowInstance.NoButtonElement);
                    objMessageWindowInstance.YesButtonElement.SetValue(ModalDialog.ActionResult, DialogResult.Yes);
                    objMessageWindowInstance.NoButtonElement.SetValue(ModalDialog.ActionResult, DialogResult.No);
                    break;

                case MessageWindowButtons.YesNoCancel:
                    objMessageWindowInstance.ButtonHolderElement.Children.Add(objMessageWindowInstance.YesButtonElement);
                    objMessageWindowInstance.ButtonHolderElement.Children.Add(objMessageWindowInstance.NoButtonElement);
                    objMessageWindowInstance.ButtonHolderElement.Children.Add(objMessageWindowInstance.CancelButtonElement);
                    objMessageWindowInstance.YesButtonElement.SetValue(ModalDialog.ActionResult, DialogResult.Yes);
                    objMessageWindowInstance.NoButtonElement.SetValue(ModalDialog.ActionResult, DialogResult.No);
                    objMessageWindowInstance.CancelButtonElement.SetValue(ModalDialog.ActionResult, DialogResult.Cancel);
                    break;

                case MessageWindowButtons.RetryCancel:
                    objMessageWindowInstance.ButtonHolderElement.Children.Add(objMessageWindowInstance.RetryButtonElement);
                    objMessageWindowInstance.ButtonHolderElement.Children.Add(objMessageWindowInstance.CancelButtonElement);
                    objMessageWindowInstance.RetryButtonElement.SetValue(ModalDialog.ActionResult, DialogResult.Retry);
                    objMessageWindowInstance.CancelButtonElement.SetValue(ModalDialog.ActionResult, DialogResult.Cancel);
                    break;

                case MessageWindowButtons.AbortRetryIgnore:
                    objMessageWindowInstance.ButtonHolderElement.Children.Add(objMessageWindowInstance.AbortButtonElement);
                    objMessageWindowInstance.ButtonHolderElement.Children.Add(objMessageWindowInstance.RetryButtonElement);
                    objMessageWindowInstance.ButtonHolderElement.Children.Add(objMessageWindowInstance.IgnoreButtonElement);
                    objMessageWindowInstance.AbortButtonElement.SetValue(ModalDialog.ActionResult, DialogResult.Abort);
                    objMessageWindowInstance.RetryButtonElement.SetValue(ModalDialog.ActionResult, DialogResult.Retry);
                    objMessageWindowInstance.CancelButtonElement.SetValue(ModalDialog.ActionResult, DialogResult.Cancel);
                    break;

            }

            //Display the appropriate icon
            Image imgIcon = null;
            switch (icon)
            {
                case MessageWindowIcon.Error:
                    imgIcon = objMessageWindowInstance.MessageIconErrorElement;
                    //imgIcon.Source = Application.Current.Resources[""
                    if (objMessageWindowInstance.MessageIconErrorElement != null)
                        objMessageWindowInstance.MessageIconErrorElement.Visibility = Visibility.Visible;
                    break;

                case MessageWindowIcon.Information:
                    imgIcon = objMessageWindowInstance.MessageIconInfoElement;
                    if (objMessageWindowInstance.MessageIconInfoElement != null)
                        objMessageWindowInstance.MessageIconInfoElement.Visibility = Visibility.Visible;
                    break;

                case MessageWindowIcon.Question:
                    imgIcon = objMessageWindowInstance.MessageIconQuestionElement;
                    if (objMessageWindowInstance.MessageIconQuestionElement != null)
                        objMessageWindowInstance.MessageIconQuestionElement.Visibility = Visibility.Visible;
                    break;

                case MessageWindowIcon.Warning:
                    imgIcon = objMessageWindowInstance.MessageIconWarnElement;
                    if (objMessageWindowInstance.MessageIconWarnElement != null)
                        objMessageWindowInstance.MessageIconWarnElement.Visibility = Visibility.Visible;
                    break;

            }

            //Remove all icons not required
            RemoveElementFromParent(objMessageWindowInstance.MessageIconErrorElement, imgIcon);
            RemoveElementFromParent(objMessageWindowInstance.MessageIconInfoElement, imgIcon);
            RemoveElementFromParent(objMessageWindowInstance.MessageIconQuestionElement, imgIcon);
            RemoveElementFromParent(objMessageWindowInstance.MessageIconWarnElement, imgIcon);



            //Apply the style if set
            //if (DefaultStyle != null)
            //    objMessageWindowInstance.Style = DefaultStyle;

            //Ensure that the message box is displayed within the owner control bounds.
            if (owner == null)
            {
                FrameworkElement objRoot = Application.Current.RootVisual as FrameworkElement;
                if (objRoot != null)
                {
                    objMessageWindowInstance.MaxWidth = objRoot.ActualWidth;
                    objMessageWindowInstance.MaxHeight = objRoot.ActualHeight;// 

                    if (objMessageWindowInstance.MessageBorderElement != null)
                    {
                        objMessageWindowInstance.MessageBorderElement.MaxWidth = objRoot.ActualWidth;
                        objMessageWindowInstance.MessageBorderElement.MaxHeight = objRoot.ActualHeight;
                    }
                
                }

            }
            else
            {
                objMessageWindowInstance.MaxWidth = owner.ActualWidth;
                objMessageWindowInstance.MaxHeight = owner.ActualHeight;// 

                if (objMessageWindowInstance.MessageBorderElement != null)
                {
                    objMessageWindowInstance.MessageBorderElement.MaxWidth = owner.ActualWidth;
                    objMessageWindowInstance.MessageBorderElement.MaxHeight = owner.ActualHeight;
                }

            }



            //Pass the default button to foucs to the Modal dialog
            //return objMessageWindowInstance.ShowDialog(owner, objMessageWindowInstance.TitleBarElement, (Button)objMessageWindowInstance.ButtonHolderElement.Children[(int)defaultButton], true, null);

            //if (objMessageWindowInstance.MessageBorderElement is WindowPanel)
            //    ((WindowPanel)objMessageWindowInstance.MessageBorderElement)._closeElement.SetValue(ModalDialog.ActionResult, DialogResult.None);

            return objMessageWindowInstance.ShowDialog(owner, (Button)objMessageWindowInstance.ButtonHolderElement.Children[(int)defaultButton]);

        }

        private static void RemoveElementFromParent(FrameworkElement child, Image imgIconToExclude)
        {
            if (child != null && child != imgIconToExclude && child.Parent != null & child.Parent is Panel)
                ((Panel)child.Parent).Children.Remove(child);


        }

    }
}
